# token生成与解密
from jwt.exceptions import InvalidSignatureError, ExpiredSignatureError, DecodeError
from jwt import decode, encode
from common.setting import settings
from common.response import ApiResponse
from datetime import datetime, timedelta
from typing import Optional, Union
from fastapi import Header, HTTPException
from pydantic import BaseModel


class TokenData(BaseModel):
    username: Union[str, None] = None


class Token(BaseModel):
    access_token: str
    token_type: str


class MakeToken:
    # 加密密钥
    secret_key = settings.TOKEN_SECRET_KEY
    # 设置过期时间 demo 5分钟过期
    expire = datetime.utcnow() + timedelta(minutes=settings.TOKEN_EXPIRE_MINUTES)
    params = {"exp": expire}
    # 加密方式
    algorithm = 'HS256'

    token = None

    def __init__(self, args):
        self.params = {**args, **self.params}
        self.create()

    def create(self):
        token = encode(self.params, self.secret_key, algorithm=self.algorithm)
        self.token = token
        return token

    @classmethod
    def decodeToken(cls, token: str = None):
        print(token)
        try:
            payload = decode(token, cls.secret_key, algorithms=cls.algorithm)
            return payload
        except InvalidSignatureError as e:
            raise HTTPException(status_code=200,
                                detail=ApiResponse(code=200, message="无效签名", data=None).set_api_dict())
        except ExpiredSignatureError as e:
            raise HTTPException(status_code=200,
                                detail=ApiResponse(code=200, message="token过期", data=None).set_api_dict())
        except DecodeError as e:
            raise HTTPException(status_code=200,
                                detail=ApiResponse(code=200, message="token验证失败", data=None).set_api_dict())

    @classmethod
    def check_jwt_token(cls, token: Optional[str] = Header(None)):
        return cls.decodeToken(token=token)
